package com.example.application;

import java.awt.geom.GeneralPath;
import java.awt.geom.Path2D;
import java.awt.geom.Point2D;
import java.awt.geom.QuadCurve2D;

/**
 * @author: xiaoqing
 * @date: 2022/4/9 4:45 PM
 * @description: Line
 **/
public class Line {

    private LineType lineType;

    public LineType getLineType() {
        return lineType;
    }

    public void setLineType(LineType lineType) {
        this.lineType = lineType;
    }

    public boolean isSelected;
    public boolean isSelectP0; //选择线段的第一个端点
    public boolean isSelectP1; //选择线段的另一个端点
    public boolean isSelectP2; //选择线段的中间的端点
    public double distance;    //实际线的长度
    public double length;      //所画的线的长度
    public GeneralPath shape;  //线的构造路径
    private float len = 3.0f;  //线宽的改变主要靠该参数

    private int id;
    public  int startX,startY,endX,endY,middleX,middleY;
    public  int lineShape;     //线形状 0直线1折线2曲线
    public  float lineWidth = 0.6f; // 画笔宽
    //private LineType lineType;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public   float getLen() {
        return this.len;
    }

    public   void setLen(float len) {
        this.len = len;
    }

    public double getDistance() {
        return distance;
    }

    public void setDistance(double distance) {
        this.distance = distance;
    }

//    public LineType getLineType() {
//        return lineType;
//    }
//    public void setLineType(LineType lineType) {
//        this.lineType = lineType;
//    }


    public int getStartX() {
        return startX;
    }

    public void setStartX(int startX) {
        this.startX = startX;
    }

    public int getStartY() {
        return startY;
    }

    public void setStartY(int startY) {
        this.startY = startY;
    }

    public int getEndX() {
        return endX;
    }

    public void setEndX(int endX) {
        this.endX = endX;
    }

    public int getEndY() {
        return endY;
    }

    public void setEndY(int endY) {
        this.endY = endY;
    }

    public int getMiddleX() {
        return middleX;
    }

    public void setMiddleX(int middleX) {
        this.middleX = middleX;
    }

    public int getMiddleY() {
        return middleY;
    }

    public void setMiddleY(int middleY) {
        this.middleY = middleY;
    }

    public int getLineShape() {
        return lineShape;
    }

    public void setLineShape(int lineShape) {
        this.lineShape = lineShape;
    }

    /**
     * @Description 构造线路径 ,Polyline 为0：直线；1折线；2：曲线
     * 可以使用的策略模式，针对不同的lineShape，分配不同的路径算法（降低耦合度）
     */
    public void constructShape() {
//GeneralPath 类表示根据直线、二次曲线和三次 (Bézier) 曲线构造的几何路径
        shape = new GeneralPath();

        switch (lineShape) {
            case 0://直线
                straightLine();
                break;
            case 1://折线
                polygonalLine();
                break;
            case 2://曲线
                curveLine();
                break;
            default:
                break;
        }
    }
    /**
     * @Description 画曲线，曲线路径的定义
     */
    private void curveLine() {

        double[] px = new double[6];
        double[] py = new double[6];
        int a,b,c,d;
        if(startY>=endY){
            a = endX;
            b = endY;
            c = startX;
            d = startY;
        }else{
            a = startX;
            b = startY;
            c = endX;
            d = endY;
        }

        px[0] = a;
        py[0] = b;
        px[4] = middleX;
        py[4] = middleY;
        px[1] = c;
        py[1] = d;

        double sina = (middleY-b)/Math.hypot(middleY-b,middleX-a);
        double cosa=(middleX-a)/Math.hypot(middleY-b,middleX-a);
        double cosa1=(a-middleX)/Math.hypot(middleY-b,middleX-a);
        double sinb=(d-middleY)/Math.hypot(d-middleY,middleX-c);
        double cosb=(middleX-c)/Math.hypot(d-middleY,middleX-c);
        double cosb1=(c-middleX)/Math.hypot(d-middleY,c-middleX);
        if(middleX>=a&&middleX<=c){

            px[2] = c +len*sinb;
            py[2] = d +len*cosb;
/*px[5] =(cosa*sinb*(c +len*sinb)+sina*cosb*(a+len*sina)-cosb*cosa*(b -len*cosa)+cosb*cosa*(d +len*cosb))/(cosa*sinb+sina*cosb);
     py[5] = b -len*cosa+sina/cosa*(px[5]-a+len*sina);*/
            px[5] = middleX+len*Math.sqrt(2)/2;
            py[5] = middleY-len*Math.sqrt(2)/2;
            px[3] = a+len*sina;
            py[3] = b -len*cosa;
        }else if(middleX==a&&middleX>c){

            px[2] = c;
            py[2] = d-len ;
            px[5] = middleX-len;
            py[5] = middleY-len;
            px[3] = a -len;
            py[3] = b;
        }
        else {

            px[2] = c-len* sinb;
            py[2] = d+len*cosb1;
            px[5] =(cosa1*cosb1*(b -len*cosa1)+cosb1*(a-len*sina)*sina-cosa1*cosb1*(d+len*cosb1)+cosa1*sinb*(c-len* sinb))/(cosa1*sinb+sina*cosb1);
            py[5] = ((a-len*sina)-px[5])*sina/cosa1+(b -len*cosa1);
            px[3] = a-len*sina;
            py[3] = b -len*cosa1;
        }
//二次曲线函数
        QuadCurve2D.Double quadCurve2D_double1=new QuadCurve2D.Double(px[0], py[0],px[4], py[4], px[1], py[1]);
        QuadCurve2D.Double quadCurve2D_double2=new QuadCurve2D.Double(px[2], py[2],px[5], py[5], px[3], py[3]);

        shape=new GeneralPath(quadCurve2D_double1);
        shape.lineTo(px[2], py[2]);
        shape.append(quadCurve2D_double2,true);
        shape.lineTo(px[0], py[0]);
        shape.closePath();
/*int x=(int) (quadCurve2D_double1.getBounds2D().getCenterX());
int y = 0;
if(startX-2*middleX+endX!=0){
贝塞尔曲线
 * y=(1-t)^2P0+2t(1-t)P1+t^2P2
 *
double t= (2*startX-2*middleX-Math.sqrt(4*(startX-middleX)*(startX-middleX)-4*(startX-2*middleX+endX)*(startX-x)))/(2*(startX-2*middleX+endX));
if(t>0&&t<1){
y =(int) ((1-t)*(1-t)*startY+2*t*(1-t)*middleY+t*t*endY);
}else{
double t1= (2*startX-2*middleX+Math.sqrt(4*(startX-middleX)*(startX-middleX)-4*(startX-2*middleX+endX)*(startX-x)))/(2*(startX-2*middleX+endX));
y =(int) ((1-t1)*(1-t1)*startY+2*t1*(1-t1)*middleY+t1*t1*endY);
}
}else{
y=(startY+endY)/2;
}*/
    }

    /**
     * @Description 画折线，折线路径的定义
     */
    private void polygonalLine() {


        double[] px = new double[6];
        double[] py = new double[6];


        if((startX>endX&&startY>endY)||(startX<endX&&startY<endY)){
            px[0] = startX ;
            py[0] = startY ;
            px[5] = endX ;
            py[5] = startY ;
            px[1] = endX ;
            py[1] = endY ;
            px[2] = endX + len;
            py[2] = endY ;
            px[4] = endX + len;
            py[4] = startY - len ;
            px[3] = startX ;
            py[3] = startY - len ;
        }else{
            px[0] = startX ;
            py[0] = startY ;
            px[5] = endX ;
            py[5] = startY ;
            px[1] = endX ;
            py[1] = endY ;
            px[2] = endX + len;
            py[2] = endY ;
            px[4] = endX + len;
            py[4] = startY + len ;
            px[3] = startX ;
            py[3] = startY + len ;
        }


        startX=(int) px[0];
        startY=(int) py[0];
        endX=(int) px[1];
        endY=(int) py[1];
        middleX=(int) px[5];
        middleY=(int) py[5];
/*
 *折线是否变成直线
 *
 * x2=e;
           y2=f;*/
        shape.moveTo(px[0], py[0]);//通过移动到指定坐标（以双精度指定），将一个点添加到路径中。
        shape.lineTo(px[5], py[5]);//通过绘制一条从当前坐标到新指定坐标（以双精度指定）的直线，将一个点添加到路径中
        shape.lineTo(px[1], py[1]);
        shape.lineTo(px[2], py[2]);
        shape.lineTo(px[4], py[4]);
        shape.lineTo(px[3], py[3]);
//通过绘制一条向后延伸到最后一个 moveTo 的坐标的直线，封闭当前子路径。如果该路径已封闭，则此方法无效
        shape.closePath();
    }

    /**
     * @Description 画直线，直线路径的定义
     */
    private void straightLine() {

        length = Math.hypot(endX - startX, endY - startY);//直线的长度  返回 sqrt(x^2 +y^2)，没有中间溢出或下溢。
        double[] px = new double[4];
        double[] py = new double[4];

        if (endX == startX) { //竖直线
            middleX=endX;
            middleY=(endY+startY)/2;
            px[0] = startX;
            py[0] = startY;
            px[1] = endX  ;
            py[1] = endY;
            px[2] = endX - len;
            py[2] = endY;
            px[3] = startX - len;
            py[3] = startY;
        } else if (endY == startY) { //横直线
            middleX=(startX+endX)/2;
            middleY=endY;
            px[0] = startX;
            py[0] = startY;
            px[1] = endX;
            py[1] = endY ;
            px[2] = endX;
            py[2] = endY + len;
            px[3] = startX;
            py[3] = startY + len;
        } else {//斜线
            double sin = (endX - startX) / length;
            double cos = (endY - startY) / length;
            if(startX<endX){
                middleX=startX+Math.abs (endX - startX) /2;
            }else{
                middleX=endX+Math.abs (endX - startX) /2;
            }
            if(startY>endY){
                middleY=endY+Math.abs((endY-startY)/2);
            }else{
                middleY=startY+Math.abs((endY-startY)/2);
            }
            px[0] = startX + len * cos;
            py[0] = startY - len * sin;
            px[1] = endX + len * cos;
            py[1] = endY - len * sin;
            px[2] = endX - len * cos;
            py[2] = endY + len * sin;
            px[3] = startX - len * cos;
            py[3] = startY + len * sin;
        }
/*x2=e;
y2=f;*/
        shape.moveTo(px[0], py[0]);//通过移动到指定坐标（以双精度指定），将一个点添加到路径中。
        shape.lineTo(px[1], py[1]);//通过绘制一条从当前坐标到新指定坐标（以双精度指定）的直线，将一个点添加到路径中
        shape.lineTo(px[2], py[2]);
        shape.lineTo(px[3], py[3]);
        shape.closePath();
    }

    /**
     * @Description判断鼠标是否移到路径对象上
     * */
    public boolean contains(int x, int y) {
        return Path2D.contains(shape.getPathIterator(null), new Point2D.Float(x, y));
    }
}
